﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using TimerJobServer.Common;
using log4net;
using Quartz;

namespace TimerJobServer
{
    /// <summary>
    /// 执行的工作
    /// </summary>
    public class QuartzJob : IJob
    {

        private readonly ILog logger = LogManager.GetLogger(typeof(QuartzJob));

        public void Execute(IJobExecutionContext context)
        {
            try
            {
                QuarzJobInfo job = context.JobDetail.JobDataMap.Get("QuarzJobInfo") as QuarzJobInfo;
                currentJob = job;
                ExeJob(job);
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
             }
        }

        public void ExeJob(QuarzJobInfo job)
        {
            switch (job.JobType)
            {
                case QuarzJobType.Dll:
                    DoDllJob(job);
                    break;
                //case QuarzJobType.CS:
                //    DoCsJob(job);
                //    break;
                case QuarzJobType.Exe:
                    DoExeJob(job);
                    break;
                case QuarzJobType.HttpGet:
                    DoHttpGet(job);
                    break;
                case QuarzJobType.HttpPost:
                    DoHttpPost(job);
                    break;
                default:
                    break;
            }
        }

        private void DoHttpPost(QuarzJobInfo job)
        {
            if (string.IsNullOrEmpty(job.HttpURL))
            {
                logger.Error("HttpPost请求地址为空!");
            }
            else
            {
                string result = HttpPost(job.HttpURL, job.HttpPostDate,job.HttpHeaderDic);
                logger.Info(result);
            }
        }

        public string HttpPost(string url, string paramData, List<HttpHeader> headerDic = null)
        {
            string result = string.Empty;
            try
            {
                HttpWebRequest wbRequest = (HttpWebRequest)WebRequest.Create(url);
                wbRequest.Method = "POST";
                wbRequest.ContentType = "application/x-www-form-urlencoded";
                wbRequest.ContentLength = Encoding.UTF8.GetByteCount(paramData);
                if (headerDic != null && headerDic.Count > 0)
                {
                    foreach (var item in headerDic)
                    {
                        if (!string.IsNullOrEmpty(item.Key) && !string.IsNullOrEmpty(item.Value))
                        {
                            if (item.Key == "Content-Type")
                            {
                                wbRequest.ContentType = item.Value;
                            }
                            else if (item.Key == "User-Agent")
                            {
                                wbRequest.UserAgent = item.Value;
                            }
                            else if (item.Key == "Referer")
                            {
                                wbRequest.Referer = item.Value;
                            }
                            else
                                wbRequest.Headers.Add(item.Key, item.Value);
                        }
                    }
                }


                using (Stream requestStream = wbRequest.GetRequestStream())
                {
                    using (StreamWriter swrite = new StreamWriter(requestStream))
                    {
                        swrite.Write(paramData);
                    }
                }
                HttpWebResponse wbResponse = (HttpWebResponse)wbRequest.GetResponse();
                using (Stream responseStream = wbResponse.GetResponseStream())
                {
                    using (StreamReader sread = new StreamReader(responseStream))
                    {
                        result = sread.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
            }
            return result;
        }

        

        private void DoHttpGet(QuarzJobInfo job)
        {
            string result = string.Empty;
            if (string.IsNullOrEmpty(job.HttpURL))
            {
                logger.Error("HttpGet请求地址为空!");
            }
            
            try
            {
                HttpWebRequest wbRequest = (HttpWebRequest)WebRequest.Create(job.HttpURL);
                wbRequest.Method = "GET";
                HttpWebResponse wbResponse = (HttpWebResponse)wbRequest.GetResponse();
                using (Stream responseStream = wbResponse.GetResponseStream())
                {
                    using (StreamReader sReader = new StreamReader(responseStream))
                    {
                        result = sReader.ReadToEnd();
                        logger.Info(result);//返回请求
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
            }
            //return result;
        }

        private QuarzJobInfo currentJob;
        private void DoExeJob(QuarzJobInfo job)
        {
            try
            {
                string FullPath = getFullPath(job.FullPath);
                if (FullPath != null)
                {
                    FileInfo fi = new FileInfo(FullPath);
                    string fileName = fi.Name.Replace(fi.Extension,"");
                    logger.Info(fi.Name);
                    if (System.Diagnostics.Process.GetProcessesByName(fileName).Length > 0)
                    { //存在 
                        logger.Info(FullPath+"正在启动中:同时只能启动一个程序!");
                        return;
                    }
                    Process process = new Process();
                    process.StartInfo.FileName = FullPath;
                    process.StartInfo.Arguments = job.Args;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.OutputDataReceived += Process_OutputDataReceived;
                    //process.EnableRaisingEvents = true;
                    //process.Exited += Process_Exited;
                    logger.Info("exe 启动参数"+process.StartInfo.Arguments + job.Args);

                    process.Start();
                    process.BeginOutputReadLine();
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
            }
        }

        private void Process_Exited(object sender, EventArgs e)
        {
            logger.Info(currentJob.Name + "退出!");
            if (currentJob!=null)
            {
                logger.Info(currentJob.Name+"执行完成!");
            }
        }

        private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                logger.Info(e.Data);
            }
        }

        /// <summary>
        /// 执行CS文件
        /// </summary>
        /// <param name="job"></param>
        private void DoCsJob(QuarzJobInfo job)
        {
            try
            {
                if (!File.Exists(job.FullPath))
                {
                    logger.Error(job.FullPath + "文件不存在");
                    return;
                }
                object obj = null;
                Assembly assembly=null;
                Type type;
                //读取文件
                //assembly =// CSScript.LoadFile(job.FullPath);
                if (assembly == null)
                {
                    logger.Error(job.FullPath + "未找到!");
                    return;
                }
                type = assembly.GetType(job.ClassFullName);

                if (type == null)
                {
                    logger.Error(job.ClassFullName + "未找到!");
                    return;
                }
                obj = System.Activator.CreateInstance(type);

                MethodInfo method1 = type.GetMethod(job.MethodName);
                if (method1 == null)
                {
                    logger.Error(job.MethodName + "未找到!");
                    return;
                }
                method1.Invoke(obj, null); //执行操作
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
            }
        }

        /// <summary>
        /// 执行dll类型的任务
        /// </summary>
        /// <param name="job"></param>
        private void DoDllJob(QuarzJobInfo job)
        {
            try
            {
                string dllPath = getFullPath(job.FullPath);
                if (dllPath != null)
                {
                    object obj = null;
                    Assembly assembly;
                    Type type;
                    assembly = Assembly.LoadFrom(dllPath);
                    if (assembly == null)
                    {
                        logger.Error(job.FullPath + "加载失败!");
                        return;
                    }
                    type = assembly.GetType(job.ClassFullName);
                    if (type == null)
                    {
                        logger.Error(job.ClassFullName + "未找到!");
                        return;
                    }
                    obj = System.Activator.CreateInstance(type);

                    MethodInfo method1 = type.GetMethod(job.MethodName);
                    if (method1 == null)
                    {
                        logger.Error(job.MethodName + "未找到!");
                        return;
                    }
                    method1.Invoke(obj, null); //执行操作
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
            }
        }


        /// <summary>
        /// 获取路径的决定路径 如果不存在则返回null
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string getFullPath(string path)
        {
            string FullPath = path;
            if (!File.Exists(FullPath))
            {
                 FullPath = AppDomain.CurrentDomain.BaseDirectory + path;
                if (!File.Exists(FullPath))
                {
                    logger.Error(path + "文件不存在");
                    return null;
                }
                else
                {
                    return FullPath;
                }
            }

            return FullPath;
        }
    }
}
